package cn.com.qtgl.apis.iam.model.beans;

import cn.com.qtgl.apis.iam.model.enums.DeptSuffix;
import cn.com.qtgl.apis.iam.model.enums.Wildcard;
import lombok.Getter;
import org.apache.commons.lang3.StringUtils;
import org.springframework.util.Assert;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Objects;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import java.util.stream.Collectors;

@Getter
public class UserFilters implements UserFilterApi{

    private final List<UserFilter> userFilters;

    public final static Pattern deptRegex=Pattern.compile("^(\\w*)([*+=])?$");
    public final static Pattern postRegex=Pattern.compile("^:?(\\w*)([*#])?$");

    public final static Pattern userFilterUserRegex=Pattern.compile("^::(\\w+)$");

    public final static Pattern userFilterDeptPostRegex=Pattern.compile("^(\\w+)?([*=+])?(:(\\w+))?$");

    public UserFilters(List<UserFilter> userFilters) {
        this.userFilters = userFilters;
    }

    @Override
    public String getContent() {
        return userFilters.stream().map(UserFilter::getContent).collect(Collectors.joining(","));
    }

    public static class Builder{

        private final List<UserFilter> userFilters;

        public Builder() {
            this.userFilters = new ArrayList<>();
        }
        public Builder(List<UserFilter> userFilters) {
            this.userFilters = userFilters;
        }

        public UserFilters build(){
            UserFilters userFilters=new UserFilters(this.userFilters);
            return userFilters;
        }

        public Builder addUser(String code){
            this.userFilters.add(new UserFilter(new UserFlag(code)));
            return this;
        }

        public Builder addDeptPost(String deptCode, DeptSuffix deptSuffix, String postCode){
            this.userFilters.add(new UserFilter(new DeptPostFlag(new DeptFlag(deptCode,deptSuffix),new PostFlag(postCode))));
            return this;
        }

        public Builder addDeptPost(String deptFlag,  String postFlag){
            Matcher mDept=deptRegex.matcher(deptFlag);
            Assert.isTrue(mDept.matches(),"部门信息不匹配");
            Matcher mPost=postRegex.matcher(postFlag);
            Assert.isTrue(mPost.matches(),"岗位信息不匹配");
            this.userFilters.add(new UserFilter(new DeptPostFlag(new DeptFlag(mDept.group(1),transDeptSuffix(mDept.group(2))),new PostFlag(mPost.group(1)))));
            return this;
        }

        public Builder addDeptOfficial(String deptCode){
            this.userFilters.add(new UserFilter(new DeptPostFlag(new DeptFlag(deptCode,DeptSuffix.ALL),new PostFlag("#"))));
            return this;
        }
        public Builder addDeptAll(String deptCode){
            this.userFilters.add(new UserFilter(new DeptPostFlag(new DeptFlag(deptCode,DeptSuffix.ALL),new PostFlag("*"))));
            return this;
        }

        public Builder addPostAll(String postCode){
            this.userFilters.add(new UserFilter(new DeptPostFlag(new DeptFlag("",DeptSuffix.ALL),new PostFlag(postCode))));
            return this;
        }

        public static Builder parse(String userFiltersStr){
            List<UserFilter> userFilters=Arrays.stream(userFiltersStr.split(",")).map(filter->{
                Matcher um=userFilterUserRegex.matcher(filter);
                Matcher dpm= userFilterDeptPostRegex.matcher(filter);
                if(um.matches()){
                    return new UserFilter(new UserFlag(um.group(1)));
                }else if(dpm.matches()){
                    String deptCode=dpm.group(1);
                    String deptFlag=dpm.group(2);
                    String postCode=dpm.group(4);
                    return new UserFilter(new DeptPostFlag(new DeptFlag(deptCode,transDeptSuffix(deptFlag)),new PostFlag(postCode)));
                }else{
                    return null;
                }

            }).filter(Objects::nonNull).collect(Collectors.toList());
            return new Builder(userFilters);
        }

        private static DeptSuffix transDeptSuffix(String flag){
            switch (StringUtils.defaultIfEmpty(flag,"")){
                case "*":return DeptSuffix.ALL;
                case "=":return DeptSuffix.CURRENT;
                case "+":return DeptSuffix.DEPEND;
                default:return DeptSuffix.NONE;
            }
        }

        private static Wildcard transWildcard(String flag){
            switch (StringUtils.defaultIfEmpty(flag,"")){
                case "*":return Wildcard.ALL;
                case "#":return Wildcard.OFFICIAL;
                default:return Wildcard.NONE;
            }
        }
    }
}
